package cn.com.zsw.gblog.utils;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 功能描述
 *
 * @Author zsw
 * @Date 2019-11-27
 * @Version 1.0.0
 */
@Slf4j
public class JwtUtils {
    public static final String TOKEN_HEADER = "X-Token";
    public static final String TOKEN_PREFIX = "Bearer";
    /**
     * @description 选择了记住我之后的过期时间为7天
     * @Date
     **/
    static final long EXPIRATION_REMEMBER = 604800L;
    private static final long EXPIRATION = 3600L;
    private static final long DyTime = 600L;
    /**
     * @Description 过期时间是3600秒，既是1个小时
     * @Date
     **/
    private static final String SECRET = "jwtsecretdemo";
    private static final String AES_KEY = "zsw123456zsw123456zsw123456";

    /**
     * 创建token
     * 注：如果是根据可变的唯一值来生成，唯一值变化时，需重新生成token
     *
     * @return token
     */
    public static String createToken(String userId, Map<String, Object> claims) throws Exception {

        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                // 这里要早set一点，放到后面会覆盖别的字段
                .setClaims(claims)
                .setSubject(userId)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
                .compact();
        //对生成的jwt进行加密
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue(), AES_KEY.getBytes()).getEncoded();
        SymmetricCrypto crypto = new SymmetricCrypto(SymmetricAlgorithm.DESede, key);
        String s = crypto.encryptHex(token);
        log.info("生成的token:{}", s);
        return s;
    }

    /**
     * 从token中获取用户名
     *
     * @param token
     * @return
     */
    private static String getUserId(String token) {
        return Objects.requireNonNull(getTokenBody(token)).getSubject();
    }

    /**
     * 判断token是不是快过期了，
     * ！！注意：token中的时间单位是秒（ss）
     *
     * @Author zsw
     * @Date 2019-11-28
     * @Parameter * @param token
     * @Version 1.0.0
     * @Return boolean
     */
    public static boolean isDying(String token) {
        Claims claims = JwtUtils.getTokenBody(token);
        int s = (int) claims.get("exp");
        if (System.currentTimeMillis() / 1000 + DyTime > s) {
            return true;
        }
        return false;
    }

    public static Claims getTokenBody(String token) {
        //进行解密
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue(), AES_KEY.getBytes()).getEncoded();
        SymmetricCrypto crypto = new SymmetricCrypto(SymmetricAlgorithm.DESede, key);
        token = crypto.decryptStr(token);
        return Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 生成新的token
     *
     * @param token
     * @return String
     */
    public static String generateNewToken(String token) {
        if (!isDying(token)){
            return token;
        }
        Claims claims = getTokenBody(token);
        String userId = getUserId(token);
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userId)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    public static void main(String[] args) {
        String s="whFhf8/KIDc9kDLmR22otG6C9+236GIHCwnAjTMOumhOgeSPIqRfcmmZATlvoTkd5UTXnGfYIbGw4iRwc7nA3tnwyBA12FQduH3EbCI217fMIgFH2kcnPwSN1TdVu6al7I9ITed2LuQX6D8VKEOiQ4mdbCEGCso5lghRqHhFmek7Od0lfvhuZkCmKF/hDBhNKlbiG47dlhaOuOBgHMR+Vm3oHE6ulYskomhWGajuxTIsAnKUE/yj8DuUOCeZfTKHvyfHAT5M6bzR6SkQjh8WurhKv1LM+icpdhRkxPDGocPQnQ00WBQOog1VhbIJzk9d5n6ZcHMz8NU3OslvTjKn/TrlvoyHxIc3xBo64i1MXHY5QIfmJNWFdIaiAcrlNmgU";
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue(), AES_KEY.getBytes()).getEncoded();
        SymmetricCrypto crypto = new SymmetricCrypto(SymmetricAlgorithm.DESede, key);
        System.out.println(crypto.decryptStr(s));
    }

}
